from flask import (
    Blueprint,
    views,
    render_template,
    session,
    redirect,
    url_for,
    request,
    g,
    jsonify
)
#从文件中导入函数，则在文件前面添加'.'
from .forms import (
    LoginForm,
    ResetpwdForm,
    ResetEmailForm,
    AddBannerForm,
    UpdateBannerForm,
    AddBoardForm,
    UpdateBoardForm
)
from .models import CMSUser,CMSPersmission
# .models代表同级的文件，..models代表上一级的文件
from ..models import BannerModel,BoardModel,PostModel,HighlightPostModel
from .decorators import login_required,permission_required
import config
from exts import db,mail
from utils import restful,zlcache
from flask_mail import Message
import string
import random
from tasks import send_mail


# 蓝图，浏览后端信息网页时添加'/cms'，/不要忘记
bp = Blueprint("cms",__name__,url_prefix='/cms')

#@login_required必须位于@bp.route('/')之后，否则无法找到路由
@bp.route('/')

@login_required
def index():
    # g.cms_user
    return render_template('cms/cms_index.html')

#注销，清除session里的信息
@bp.route('/logout/')
@login_required
def logout():
    #另外一种写法 session.clear(),将所有的数据清掉
    del session[config.CMS_USER_ID]
    return redirect(url_for('cms.login'))

@bp.route('/profile/')
@login_required
def profile():
    return render_template('cms/cms_profile.html')

@bp.route('/email_captcha/')
def email_captcha():
    email = request.args.get('email')
    if not email:
        return restful.params_error('请传递邮箱参数')
    source = list(string.ascii_letters)
    source.extend(map(lambda x:str(x),range(0,10)))
    # source.extend(["0",1,2,3,4,5,6,7,"8","9"]),将数字转化成字符
    #将字符拼接
    captcha = "".join(random.sample(source,6))

    #给这个邮箱发送邮件
    # message = Message('神毓逍遥', recipients=[email], body='验证码是：%s' % captcha)
    # try:
    #     mail.send(message)
    # except:
    #     return restful.server_error()
    #set中用email还是captcha，经试验，当输入captcha时修改邮箱会发生邮件退回事件
    send_mail.delay('神毓逍遥',[email],'验证码是：%s' % captcha)
    zlcache.set(email)
    return restful.success()

# @bp.route('/email/')
# def send_email():
#     message = Message('邮件发送', recipients=['563667579@qq.com'],body='测试')
#     mail.send(message)
#     return 'success'



@bp.route('/posts/')
@login_required
@permission_required(CMSPersmission.POSTER)
def posts():
    post_list = PostModel.query.all()
    return render_template('cms/cms_posts.html',posts=post_list)



@bp.route('/hpost/',methods=['POST'])
@login_required
@permission_required(CMSPersmission.POSTER)
def hpost():
    post_id = request.form.get("post_id")
    if not post_id:
        return restful.params_error('请传入帖子id！')
    post = PostModel.query.get(post_id)
    if not post:
        return restful.params_error("没有这篇帖子！")

    highlight = HighlightPostModel()
    highlight.post = post
    db.session.add(highlight)
    db.session.commit()
    return restful.success()


@bp.route('/uhpost/',methods=['POST'])
@login_required
@permission_required(CMSPersmission.POSTER)
def uhpost():
    post_id = request.form.get("post_id")
    if not post_id:
        return restful.params_error('请传入帖子id！')
    post = PostModel.query.get(post_id)
    if not post:
        return restful.params_error("没有这篇帖子！")

    highlight = HighlightPostModel.query.filter_by(post_id=post_id).first()
    db.session.delete(highlight)
    db.session.commit()
    return restful.success()


@bp.route('/comments/')
@login_required
@permission_required(CMSPersmission.COMMENTER)
def comments():
    return render_template('cms/cms_comments.html')


@bp.route('/boards/')
@login_required
@permission_required(CMSPersmission.BOARDER)
def boards():
    board_models = BoardModel.query.all()
    context = {
        'boards': board_models
    }
    return render_template('cms/cms_boards.html',**context)


@bp.route('/aboard/',methods=['POST'])
@login_required
@permission_required(CMSPersmission.BOARDER)
def aboard():
    form = AddBoardForm(request.form)
    if form.validate():
        name = form.name.data
        board = BoardModel(name=name)
        db.session.add(board)
        db.session.commit()
        return restful.success()
    else:
        return restful.params_error(message=form.get_error())


@bp.route('/uboard/',methods=['POST'])
@login_required
@permission_required(CMSPersmission.BOARDER)
def uboard():
    form = UpdateBoardForm(request.form)
    if form.validate():
        board_id = form.board_id.data
        name = form.name.data
        board = BoardModel.query.get(board_id)
        if board:
            board.name = name
            db.session.commit()
            return restful.success()
        else:
            return restful.params_error(message='没有这个板块！')
    else:
        return restful.params_error(message=form.get_error())


@bp.route('/dboard/',methods=['POST'])
@login_required
@permission_required(CMSPersmission.BOARDER)
def dboard():
    board_id = request.form.get("board_id")
    if not board_id:
        return restful.params_error('请传入板块id！')

    board = BoardModel.query.get(board_id)
    if not board:
        return restful.params_error(message='没有这个板块！')

    db.session.delete(board)
    db.session.commit()
    return restful.success()


@bp.route('/fusers/')
@login_required
@permission_required(CMSPersmission.FRONTUSER)
def fusers():
    return render_template('cms/cms_fusers.html')


@bp.route('/cusers/')
@login_required
@permission_required(CMSPersmission.CMSUSER)
def cusers():
    return render_template('cms/cms_cusers.html')


@bp.route('/croles/')
@login_required
@permission_required(CMSPersmission.ALL_PERMISSION)
def croles():
    return render_template('cms/cms_croles.html')


@bp.route('/banners/')
@login_required
def banners():
    banners = BannerModel.query.order_by(BannerModel.priority.desc()).all()
    return render_template('cms/cms_banners.html',banners=banners)


@bp.route('/abanner/',methods=['POST'])
@login_required
def abanner():
    form = AddBannerForm(request.form)
    if form.validate():
        name = form.name.data
        image_url = form.image_url.data
        link_url = form.link_url.data
        priority = form.priority.data
        banner = BannerModel(name=name,image_url=image_url,link_url=link_url,priority=priority)
        db.session.add(banner)
        db.session.commit()
        return restful.success()
    else:
        return restful.params_error(message=form.get_error())


@bp.route('/ubanner/',methods=['POST'])
@login_required
def ubanner():
    form = UpdateBannerForm(request.form)
    if form.validate():
        banner_id = form.banner_id.data
        name = form.name.data
        image_url = form.image_url.data
        link_url = form.link_url.data
        priority = form.priority.data
        banner = BannerModel.query.get(banner_id)
        if banner:
            banner.name = name
            banner.image_url = image_url
            banner.link_url = link_url
            banner.priority = priority
            db.session.commit()
            return restful.success()
        else:
            return restful.params_error(message='没有这个轮播图！')
    else:
        return restful.params_error(message=form.get_error())


@bp.route('/dbanner/',methods=['POST'])
@login_required
def dbanner():
    banner_id = request.form.get('banner_id')
    if not banner_id:
        return restful.params_error(message='请传入轮播图id！')

    banner = BannerModel.query.get(banner_id)
    if not banner:
        return restful.params_error(message='没有这个轮播图！')

    db.session.delete(banner)
    db.session.commit()
    return restful.success()



class LoginView(views.MethodView):
    # 两种方法
    def get(self,message=None):
        # 函数定义时有message，后续return返回时也需要有message，在cms_login.html页面可以定义message，让出现错误时显示错误提示信息
        return render_template('cms/cms_login.html',message=message)

    def post(self):
        # request.form 为用户提交的信息，可以了解一下request的用法
        form = LoginForm(request.form)
        # 若验证成功
        # 以下内容可以抽象数据结构
        if form.validate():
            email = form.email.data
            password = form.password.data
            remember = form.remember.data
            # 条件查询，查找第一个
            user = CMSUser.query.filter_by(email=email).first()
            # 检查密码是否相等，调用check_password函数
            if user and user.check_password(password):
                # session中保存用户ID信息，session又存储在cookie当中，为了方便输入，在config中定义CMS_USER_ID = 'a'为变量，便于不出错
                session[config.CMS_USER_ID] = user.id
                # 记住我的这个功能
                if remember:
                    #设置session过期是时间，31天
                    session.permanent = True
                #若写为return redirect(url_for('index'))，则会报错，蓝图apps下还有文件cms，cms蓝图下的视图函数index，由def 定义
                return redirect(url_for('cms.index'))
            else:
                # 若出错，则停留在当前页面，这里定义message参数时，与其对应的定义get方法时，也要定义message=None
                return self.get(message='邮箱或者密码错误')
        else:
            # 输出错误信息,取元组的信息
            # message = form.errors.popitem()[1][0]
            message = form.get_error()
            # 失败则重新渲染当前登陆的模板
            return self.get(message=message)

class ResetPwdView(views.MethodView):
    #修饰的作用
    decorator = [login_required]
    def get(self):
        return render_template('cms/cms_resetpwd.html')
    def post(self):
        form = ResetpwdForm(request.form)
        if form.validate():
            oldpwd = form.oldpwd.data
            newpwd = form.newpwd.data
            user = g.cms_user
            if user.check_password(oldpwd):
                user.password = newpwd
                db.session.commit()
                #("code":200,message="密码错误")
                # return jsonify({"code":200,"message":" "})
                return restful.success()
            else:
                return restful.params_error("旧密码错误")
                # return jsonify({"code":400,"message":"旧密码错误 "})
        else:
            # message = form.get_error()
            #不可写成return jsonify({"code":400,"message":"message"})
            # return jsonify({"code":400,"message":message})
            return restful.params_error(form.get_error())


class ResetEmailView(views.MethodView):
    #理解装饰器的作用与原理,login_required后面的()是否去掉，是否需要加单引号
    decorators = [login_required]
    def get(self):
        return render_template('cms/cms_resetemail.html')
    def post(self):
        form = ResetEmailForm(request.form)
        if form.validate():
            email = form.email.data
            g.cms_user.email = email
            db.session.commit()
            return restful.success()
        else:
            return restful.params_error(form.get_error())



# 登陆界面
bp.add_url_rule('/login/',view_func=LoginView.as_view('login'))

bp.add_url_rule('/resetpwd/',view_func=ResetPwdView.as_view('resetpwd'))

bp.add_url_rule('/resetemail/',view_func=ResetEmailView.as_view('resetemail'))